#import ("../tpl.typ"): conf
#show: doc => conf(
  [Object 的属性],
  doc
)

#outline(
  title: [目录],
  indent: auto
)

= Object 的属性

使用点语法设置的 Object 属性，可枚举、可修改、可删除。

```js
const obj = { }
obj.name = 'Tony'
obj.age = 42

Object.keys(obj) // ['name', 'age']

obj.name = 'Peter'
obj // { name: 'Peter', age: 42 }

delete obj.age
obj // { name: 'Peter' }
```

== Object.defineProperty()

`Object.defineProperty()` @object-defineProperty 可以修改属性的特性。它的语法如下：

```js
Object.defineProperty(obj, prop, descriptor)
```

其中的 `descriptor` 是属性的描述符，描述符分两类：

+ 数据描述符（data descriptor）：通过 `value` 字段直接定义属性的值，并利用 `writable` 字段控制属性是否可写
+ 存取描述符（access descriptor）：通过 `get` 和 `set` 方法定义属性的读写行为，并不直接存储值

两类描述符共有字段包括 `configurable` 和`enumerable`。

- `configurable` 决定属性是否可以被删除，以及属性描述符是否可以被修改。
- `enumerable` 决定属性是否可以在某些操作中被枚举。这些操作包括 `for...in`、`Object.keys` 等。

=== 数据描述符

使用数据描述符定一个简单属性。`enumerable`、`configurable` 和 `writable` 的默认值都是 `false`，这意味着属性默认不可枚举、不可删除、不可重新配置、不可修改。

```js
const obj = {};

Object.defineProperty(obj, 'name', { value: 'Tony' })

obj.name // 'Tony'

// name 属性不可枚举
Object.keys(obj) // []

// name 属性不可修改
obj.name = 'Peter'
obj.name // 'Tony'

// name 属性不可删除
delete obj.name // false
obj.name // 'Tony'

// name 属性不可重新配置
Object.defineProperty(obj, 'name', {
  value: 'Peter',
  writable: true,
})
// Uncaught TypeError: Cannot redefine property: name
```

`Object.hasOwn()` @object-hasOwn 静态函数可以判断对象是否拥有自有属性。这个函数被建议替代 `Object.prototype.hasOwnProperty()` @object-proto-hasOwnProperty 方法。

=== 存取描述符

TODO

#bibliography("refs.yml", title: "参考资料")